package com.reyco1.medusa.loading
{
	import com.reyco1.medusa.abstract.SmartEventDispatcher;
	import com.reyco1.medusa.data.Collection;
	import com.reyco1.medusa.events.SequenceLoaderEvent;
	import com.reyco1.medusa.util.MathUtil;
	
	import flash.system.LoaderContext;
	
	public class SequenceLoader extends SmartEventDispatcher
	{
		protected var _loadingItems:Collection;
		protected var _loaderObject:Object;
		
		private var currentLoadingIndex:int;		
		private var totalFiles:Number;		
		private var currentFileLoadPercent:Number;
		private var currentLoadPercent:Number;
		private var onComplete:Function;
		private var onProgress:Function;
		private var onFileComplete:Function;
		private var onError:Function;
		
		public function SequenceLoader(loaderObj:Object = null)
		{
			super();
			_loadingItems = new Collection();
			if(loaderObj)
			{
				loaderObject = loaderObj;
			}
		}
		
		public function add(item:LoadingItem):void
		{
			var loadingItem:LoadingItem = item;	
			loadingItem.index = loadingItems.length;
			
			var loadingParams:Object 	= {};	
			loadingParams.onProgress 	= onFileLoadProgress;
			loadingParams.onComplete 	= onFileLoadComplete;
			loadingParams.onError    	= onFileLoadError;
			loadingParams.loaderContext = new LoaderContext(true);
			
			loadingItem.loader.loaderObject = loadingParams;			
			_loadingItems.addItem( loadingItem );
		}
		
		public function addCollection(collection:Collection):void
		{
			for(var a:int = 0; a<collection.length; a++)
			{
				var loadingParams:Object 	= {};	
				loadingParams.onProgress 	= onFileLoadProgress;
				loadingParams.onComplete 	= onFileLoadComplete;
				loadingParams.onError    	= onFileLoadError;
				loadingParams.loaderContext = new LoaderContext(true);
				
				(collection.getItemAt(a) as LoadingItem).loader.loaderObject = loadingParams;
				(collection.getItemAt(a) as LoadingItem).index = a;
			}
			
			_loadingItems = collection;
		}
		
		/* public */
		
		public function load():void
		{
			if(_loadingItems.length > 0)
			{
				totalFiles = _loadingItems.length;
				loadItem( _loadingItems.getItemAt(0) as LoadingItem );
			}
			else
			{
				log("Unable to initialize sequential loading. The queue is empty!", "warning");
			}
		}
		
		public function clear():void
		{
			removeAllListeners();
			_loadingItems = null;
		}
		
		/* private */	
		
		private function loadItem(loadingItem:LoadingItem):void
		{
			currentLoadingIndex = loadingItem.index;
			loadingItem.loader.load();
		}
		
		/* handlers */
		
		private function onFileLoadProgress(progressObj:Object):void
		{
			currentFileLoadPercent  = progressObj.percent;
			currentLoadPercent		= MathUtil.percentage(currentLoadingIndex + currentFileLoadPercent, totalFiles);
			
			dispatchEvent(new SequenceLoaderEvent(SequenceLoaderEvent.PROGRESS, {currentFilePercent:currentFileLoadPercent, overallPercent:currentLoadPercent}));
			if(onProgress != null) onProgress({currentFilePercent:currentFileLoadPercent, overallPercent:currentLoadPercent});
		}
		
		private function onFileLoadComplete(content:*):void
		{
			LoadingItem( _loadingItems.getItemAt(currentLoadingIndex) ).content = content;
			LoadingItem( _loadingItems.getItemAt(currentLoadingIndex) ).loader.destroy();
			LoadingItem( _loadingItems.getItemAt(currentLoadingIndex) ).loader = null;
			LoadingItem( _loadingItems.getItemAt(currentLoadingIndex) ).loaded = true;
			
			dispatchEvent(new SequenceLoaderEvent(SequenceLoaderEvent.FILE_COMPLETE, LoadingItem( _loadingItems.getItemAt(currentLoadingIndex) )));
			if(onFileComplete != null) onFileComplete(LoadingItem( _loadingItems.getItemAt(currentLoadingIndex) ));
			
			var loadNextFile:Boolean = _loadingItems.hasNext();
			
			if( loadNextFile )
			{
				loadItem( _loadingItems.next() as LoadingItem );
			}
			else
			{
				dispatchEvent(new SequenceLoaderEvent(SequenceLoaderEvent.COMPLETE, _loadingItems));
				if(onComplete != null) onComplete(_loadingItems);
			}
		}
		
		private function onFileLoadError(message:String):void
		{
			dispatchEvent(new SequenceLoaderEvent(SequenceLoaderEvent.ERROR, message ));
			log("error loading file: " + _loadingItems.getItemAt(currentLoadingIndex).url, "fatal");
			if(onError != null) onError(message);
		}
		
		/* properties */

		public function get loadingItems():Collection
		{
			return _loadingItems;
		}
		
		public function get loaderObject():Object
		{
			return _loaderObject;
		}
		
		public function set loaderObject(value:Object):void
		{
			_loaderObject = value;
			
			onComplete 		= loaderObject.onComplete;
			onProgress 		= loaderObject.onProgress;
			onError    	 	= loaderObject.onError;
			onFileComplete 	= loaderObject.onFileComplete;
		}

	}
}